/*************************************************************************
 * File Name   : webserver.c
 * Brief       :
 * Change Logs :
 * Date           Author       Notes
 * 2021\03\07     yukelab      The first version.
*************************************************************************/
#include <rtthread.h>
#include <mongoose.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netdev.h>
#include "info.h"

#define DBG_SECTION_NAME               "web.server"
// #define DEV_DEBUG
#ifdef DEV_DEBUG
    #define DBG_LEVEL                      DBG_LOG
#else
    #define DBG_LEVEL                      DBG_INFO
#endif /* DEV */

#include <rtdbg.h>

static struct mg_mgr mgr;
static struct mg_http_serve_opts opts;
// NOTE: Set actual board IP addres in Inc/main.h
// Default address is 192.168.0.10
static const char *s_listening_address = "http://0.0.0.0:80";
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data)
{
    if (ev == MG_EV_HTTP_MSG)
    {
        struct mg_http_message *hm = (struct mg_http_message *) ev_data;
        if (mg_http_match_uri(hm, "/say"))
        {
            LOG_I("mg http reply /say");
            mg_http_reply(c, 200, "", "hello, %s!\n", "world");
        }
        else if (mg_http_match_uri(hm, "/info"))
        {
            char *s = get_info();
            if (s != RT_NULL)
            {
                mg_http_reply(c, 200, "Content-Type: application/json;  charset=utf-8\r\n", "%s", s);
            }
            else
            {
                mg_http_reply(c, 204, "Content-Type: application/json;  charset=utf-8\r\n", "{}");
            }
        }
        else
        {
            // mg_fs default file systerm interface can not process romfs
            // Although mg src says supports posix interface
            // But its POSIX interface is wrapped in the standard library
            // it does not support romfs in rt-thread
            // so i write a mg_fs_rtt using RT-Thread DFS that support POSIX
            // POSIX open/close/read/write/seek
            extern struct mg_fs mg_fs_rtt;
            memset(&opts, 0, sizeof(opts));
            opts.root_dir = "./mongoose";  // Serve current directory
            opts.fs = &mg_fs_rtt;
            mg_http_serve_dir(c, (struct mg_http_message *) ev_data, &opts);
        }
    }
    else if (ev == MG_EV_ACCEPT)
    {
        uint8_t *addr = (uint8_t *)&c->peer.ip;
        LOG_I("connect from ip: %d.%d.%d.%d:%d", *addr, *(addr + 1), *(addr + 2), *(addr + 3), ntohs(c->peer.port));
    }
    (void) fn_data;
    (void) ev_data;
}

static void server(void *args)
{
    struct netdev *ndev = netdev_get_by_name("W5500");
    if (ndev == RT_NULL)
    {
        LOG_E("can not found w5500");
        return;
    }
    while (1)
    {
        if (1 == netdev_is_link_up(ndev))
        {
            break;
        }
        rt_thread_mdelay(500);
    }
    // mg_log_set("4");
    mg_mgr_init(&mgr);
    LOG(LL_INFO, ("Starting Mongoose v%s", MG_VERSION)); // Tell the world
    LOG(LL_DEBUG, ("Starting Mongoose v%s", MG_VERSION)); // Tell the world
    void *c = mg_http_listen(&mgr, s_listening_address, cb, &mgr); // Web listener
    if (c == NULL)
    {
        LOG_E("Create listen port error");
    }

    while (1)
    {
        mg_mgr_poll(&mgr, 1000); // Infinite event loop
    }
    mg_mgr_free(&mgr); // Unreachable
}

int start_mongoose(void)
{
    rt_thread_t tid;

    tid = rt_thread_create("MG",
                           server, RT_NULL,
                           4096, 15, 5);
    if (RT_NULL != tid)
    {
        rt_thread_startup(tid);
        return RT_EOK;
    }
    return -RT_ERROR;
}
INIT_APP_EXPORT(start_mongoose);
MSH_CMD_EXPORT(start_mongoose, upload data json to web);
